package com.mz361.common.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Tuple;

import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class RedisUtil {

    @Autowired
    private JedisPool jedisPool;

    public void setValue(String key, String value) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.set(key, value);
        }
    }

    /**
     * 如果 key 已经存在并且是一个字符串， APPEND 命令将 value 追加到 key 原来的值的末尾。
     * 如果 key 不存在， APPEND 就简单地将给定 key 设为 value ，就像执行 SET key value 一样。
     *
     * @param key
     * @param value
     */
    public void append(String key, String value) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.append(key, value);
        }
    }

    public void setexValue(String key, long seconds, String value) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.setex(key, seconds, value);
        }
    }

    /**
     * 检查给定 key 是否存在。
     *
     * @param key
     * @return
     */
    public boolean exists(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.exists(key);
        }
    }

    /**
     * 检查给定 key 是否存在。
     *
     * @param key
     * @return
     */
    public Set<String> hKeys(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hkeys(key);
        }
    }


    /**
     * 查看哈希表 key 中，给定域 field 是否存在。
     *
     * @param key
     * @param field
     * @return
     */
    public boolean hexists(String key, String field) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hexists(key, field);
        }
    }

    /**
     * 将 oldkey 改名为 newkey
     * 当 key 和 newkey 相同，或者 key 不存在时，返回一个错误。
     * 当 newkey 已经存在时， RENAME 命令将覆盖旧值。
     *
     * @param oldkey
     * @param newkey
     */
    public void rename(String oldkey, String newkey) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.rename(oldkey, newkey);
        }
    }

    /**
     * 删除给定的一个或多个 key 。
     *
     * @param keys
     * @return
     */
    public long del(String... keys) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.del(keys);
        }
    }

    /**
     * 移除给定 key 的生存时间，
     * 将这个 key 从『易失的』(带生存时间 key )转换成『持久的』
     * (一个不带生存时间、永不过期的 key )。
     *
     * @param key
     * @return
     */
    public long persist(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.persist(key);
        }
    }

    /**
     * 为给定 key 设置生存时间，当 key 过期时(生存时间为 0 )，它会被自动删除。
     *
     * @param key
     * @param seconds
     * @return
     */
    public long expire(String key, long seconds) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.expire(key, seconds);
        }
    }


    public String getValue(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.get(key);
        }
    }

    /**
     * 返回 key 中字符串值的子字符串，
     * 字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public String getRange(String key, long start, long end) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.getrange(key, start, end);
        }
    }

    public List<String> Lrange(String key, long start, long end) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.lrange(key, start, end);
        }
    }

    /**
     * 将 key 中储存的数字值增一。
     * 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCR 操作。
     *
     * @param key
     * @return
     */
    public long incr(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.incr(key);
        }
    }

    /**
     * 将 key 所储存的值加上增量 increment 。
     * 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCRBY 命令。
     *
     * @param key
     * @param increment
     * @return
     */
    public long incrBy(String key, long increment) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.incrBy(key, increment);
        }
    }

    /**
     * 同时设置一个或多个 key-value 对。
     * [key value ...]
     * MSETNX 是原子性的 所有字段要么全被设置，要么全不被设置。
     *
     * @param keyvalues
     */
    public void MSETNX(String... keyvalues) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.msetnx(keyvalues);
        }
    }

    /**
     * @param keys
     * @return 返回所有(一个或多个)给定 key 的值。
     */
    public List<String> mget(String... keys) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.mget(keys);
        }
    }

    /**
     * 返回 key 所储存的字符串值的长度。
     *
     * @param key
     * @return
     */
    public long strlen(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.strlen(key);
        }
    }

    /**
     * 将哈希表 key 中的域 field 的值设为 value 。
     *
     * @param key
     * @param field
     * @param value
     */
    public void hSet(String key, String field, String value) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.hset(key, field, value);
        }
    }

    /**
     * 删除 key field
     *
     * @param key
     * @param field
     */
    public void hDel(String key, String field) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.hdel(key, field);
        }
    }

    /**
     * 返回哈希表 key 中给定域 field 的值。
     *
     * @param key
     * @param field
     * @return
     */
    public String hGet(String key, String field) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hget(key, field);
        }
    }

    /**
     * 返回哈希表 key 中，所有的域和值。
     *
     * @param key
     * @return
     */
    public Map<String, String> hGetAll(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hgetAll(key);
        }
    }

    /**
     * 将一个或多个值 value 插入到列表 key 的表头
     * 列表允许重复元素
     *
     * @param key
     * @param values
     * @return
     */
    public long lPush(String key, String... values) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.lpush(key, values);
        }
    }

    /**
     * 取值
     *
     * @param key
     * @param start
     * @param stop
     * @return
     */
    public List<String> lRange(String key, Long start, Long stop) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.lrange(key, start, stop);
        }
    }


    /**
     * 移除并返回列表 key 的头元素。
     *
     * @param key
     * @return
     */
    public String lPop(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.lpop(key);
        }
    }

    /**
     * 将一个或多个值 value 插入到列表 key 的表尾
     * 列表允许重复元素
     *
     * @param key
     * @param values
     * @return
     */
    public long rPush(String key, String... values) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.rpush(key, values);
        }
    }

    /**
     * 移除并返回列表 key 的尾元素。
     *
     * @param key
     * @return
     */
    public String rPop(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.rpop(key);
        }
    }

    /**
     * 将信息 message 发送到指定的频道 channel 。
     *
     * @param channel
     * @param message
     * @return
     */
    public boolean publish(String channel, String message) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.publish(channel, message) > 0 ? true : false;
        }
    }

    /**
     * 命令对有序集合中指定成员的分数加上增量 1
     *
     * @param key
     * @param keyword
     */
    public void incrementKeyword(String key, String keyword) {
        try (Jedis jedis = jedisPool.getResource()) {
            // 将搜索次数加1，如果关键字不存在则初始化为1
            if (!jedis.exists(key)) {
                jedis.zadd(key, 0, keyword);
            }
            jedis.zincrby(key, 1, keyword);
        }
    }

    /**
     * 取排名
     *
     * @param key
     * @param topN
     * @return
     */
    public Set<Tuple> getTopKeywords(String key, int topN) {
        Set<Tuple> topKeywords;
        try (Jedis jedis = jedisPool.getResource()) {
            // 获取排名前N的关键字
            topKeywords = jedis.zrevrangeWithScores(key, 0, topN - 1);

        }
        return topKeywords;
    }


}
